﻿Imports System.Reflection
Imports System.ServiceModel.Activation

' NOTE: If you change the class name "FileManagerService" here, you must also update the reference to "FileManagerService" in Web.config and in the associated .svc file.
<AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Allowed)> _
Public Class FileManagerService
    Implements IFileManagerService

    Private EventHandlerObj As Object
    Public Sub New()
        'Adding handling of events
        'Dim CRUD_events As New FileIO_CRUD
        Dim FileIOCrudClassName = Web.Configuration.WebConfigurationManager.AppSettings("FileIO:CrudClassName")
        If Not String.IsNullOrEmpty(FileIOCrudClassName) Then
            EventHandlerObj = BindEvents.CreateInstanceFromClassName(FileIOCrudClassName)
            BindEvents.BindEventsByName(Me, EventHandlerObj, True, "On", String.Empty)
        End If
    End Sub
    'Public Function GetData(ByVal value As Integer) As String Implements IFileManagerService.GetData
    '    Return String.Format("You entered: {0}", value)
    'End Function
    'Public Function GetDataUsingDataContract(ByVal composite As CompositeType) As CompositeType Implements IFileManagerService.GetDataUsingDataContract
    '    If composite.BoolValue Then
    '        composite.StringValue = (composite.StringValue & "Suffix")
    '    End If
    '    Return composite
    'End Function

#Region "Folders"
    Public Function GetFolders(ByVal FolderPath As String, ByVal FolderName As String) As List(Of ServerFolder) _
      Implements IFileManagerService.GetFolders
        Try
            Return File_IO.GetFolders(FolderPath, FolderName)
        Catch ex As Exception
            Logging.LogError(ex, "GetFolders")
        End Try
        Return Nothing
    End Function
    Public Event FolderAdding As FolderAddingEventHandler Implements IFileManagerService.FolderAdding
    Public Event FolderAdded As FolderAddedEventHandler Implements IFileManagerService.FolderAdded
    Public Function AddFolder(ByVal FolderPath As String, ByVal Foldername As String) As String _
      Implements IFileManagerService.AddFolder
        Try
            Dim argsAdding As New FolderAddingEventArgs(FolderPath, Foldername)
            RaiseEvent FolderAdding(Me, argsAdding)
            Dim returnvalue = File_IO.AddFolder(FolderPath, Foldername)
            FileManager.FileTree.LoadSubfolders()
            Dim argsAdded As New FolderAddedEventArgs(FolderPath, Foldername)
            RaiseEvent FolderAdded(Me, argsAdded)
            Return returnvalue
        Catch ex As Exception
            Throw ex
        End Try
    End Function
    Public Event FolderDeleting As FolderDeletingEventHandler Implements IFileManagerService.FolderDeleting
    Public Event FolderDeleted As FolderDeletedEventHandler Implements IFileManagerService.FolderDeleted
    Public Function DeleteFolder(ByVal FolderPath As String, ByVal Foldername As String) As String _
      Implements IFileManagerService.DeleteFolder
        Try
            Dim argsDeleting As New FolderDeletingEventArgs(FolderPath, Foldername)
            RaiseEvent FolderDeleting(Me, argsDeleting)
            If argsDeleting.ReturnValue = 0 Then
                Return "Folder not deleted, folder still linked"
            Else
                Dim returnvalue = File_IO.DeleteFolder(FolderPath, Foldername)
                FileManager.FileTree.LoadSubfolders()
                Dim argsDeleted As New FolderDeletedEventArgs(FolderPath, Foldername)
                RaiseEvent FolderDeleted(Me, argsDeleted)
                Return returnvalue
            End If
        Catch ex As Exception
            Throw ex
        End Try
    End Function
    Public Event FolderUpdating As FolderUpdatingEventHandler Implements IFileManagerService.FolderUpdating
    Public Event FolderUpdated As FolderUpdatedEventHandler Implements IFileManagerService.FolderUpdated
    Public Function UpdateFolder(ByVal OrigFolderPath As String, ByVal OrigFolderName As String, ByVal NewFolderPath As String, ByVal NewFolderName As String) As String _
      Implements IFileManagerService.UpdateFolder
        Try
            Dim argsUpdating As New FolderUpdatingEventArgs(OrigFolderPath, OrigFolderName, NewFolderPath, NewFolderName)
            RaiseEvent FolderUpdating(Me, argsUpdating)
            Dim returnvalue = File_IO.UpdateFolder(OrigFolderPath, OrigFolderName, NewFolderPath, NewFolderName)
            FileManager.FileTree.LoadSubfolders()
            Dim argsUpdated As New FolderUpdatedEventArgs(OrigFolderPath, OrigFolderName, NewFolderPath, NewFolderName)
            RaiseEvent FolderUpdated(Me, argsUpdated)
            Return returnvalue
        Catch ex As Exception
            Throw ex
        End Try
    End Function
#End Region
#Region "Files"
    Public Function GetFiles(ByVal FilePath As String, ByVal FileName As String) As List(Of ServerFile) _
      Implements IFileManagerService.GetFiles
        Return File_IO.GetFiles(FilePath, FileName)
    End Function
    Public Function GetAllFileNames(ByVal baseDir As String) As String() _
      Implements IFileManagerService.GetAllFileNames
        Return File_IO.GetAllFileNames(baseDir)
    End Function
    Public Event FileDeleting As FileDeletingEventHandler Implements IFileManagerService.FileDeleting
    Public Event FileDeleted As FileDeletedEventHandler Implements IFileManagerService.FileDeleted
    Public Function DeleteFile(ByVal FilePath As String, ByVal FileName As String) As String _
      Implements IFileManagerService.DeleteFile
        Try
            Dim argsDeleting As New FileDeletingEventArgs(FilePath, FileName)
            RaiseEvent FileDeleting(Me, argsDeleting)
            If argsDeleting.ReturnValue = 0 Then
                Return "File not deleted, file still linked"
            Else
                Dim returnvalue = File_IO.DeleteFile(FilePath, FileName)
                FileManager.FileTree.LoadSubfolders()
                Dim argsDeleted As New FileDeletedEventArgs(FilePath, FileName)
                RaiseEvent FileDeleted(Me, argsDeleted)
                Return returnvalue
            End If
        Catch ex As Exception
            Throw ex
        End Try
    End Function
    Public Event FileUpdating As FileUpdatingEventHandler Implements IFileManagerService.FileUpdating
    Public Event FileUpdated As FileUpdatedEventHandler Implements IFileManagerService.FileUpdated
    Public Function UpdateFile(ByVal OrigFolderPath As String, ByVal OrigFileName As String, ByVal NewFolderPath As String, ByVal NewFileName As String) As String _
      Implements IFileManagerService.UpdateFile
        Try
            Dim argsUpdating As New FileUpdatingEventArgs(OrigFolderPath, OrigFileName, NewFolderPath, NewFileName)
            RaiseEvent FileUpdating(Me, argsUpdating)
            Dim returnvalue = File_IO.UpdateFile(OrigFolderPath, OrigFileName, NewFolderPath, NewFileName)
            FileManager.FileTree.LoadSubfolders()
            Dim argsUpdated As New FileUpdatedEventArgs(OrigFolderPath, OrigFileName, NewFolderPath, NewFileName)
            RaiseEvent FileUpdated(Me, argsUpdated)
            Return returnvalue
        Catch ex As Exception
            Throw ex
        End Try
    End Function
#End Region
#Region "Extra"
    Public Function GetFileTreeAll() As List(Of ServerFolder) _
      Implements IFileManagerService.GetFileTreeAll
        Try
            Return FileManager.FileTree.SubFolders
        Catch ex As Exception
            Logging.LogError(ex, "GetFileTreeAll")
        End Try
        Return Nothing
    End Function
    Public Function GetFileTreeDomain(ByVal domain As String) As List(Of ServerFolder) _
      Implements IFileManagerService.GetFileTreeDomain
        Dim returnList As New List(Of ServerFolder)
        Try
            For Each item In FileManager.FileTree.SubFolders.First.SubFolders
                If item.FolderName.ToLower = domain.ToLower Then
                    returnList.Add(item)
                    Return returnList
                End If
            Next
            Return FileManager.FileTree.SubFolders
        Catch ex As Exception
            Logging.LogError(ex, "GetFileTreeDomain")
        End Try
        Return returnList
    End Function
    Public Function GetFileTreeDomainAndType(ByVal domain As String, ByVal typepath As String) As List(Of ServerFolder) _
      Implements IFileManagerService.GetFileTreeDomainAndType
        Dim returnList As New List(Of ServerFolder)
        Try
            For Each item In FileManager.FileTree.SubFolders.First.SubFolders
                If item.FolderName.ToLower = domain.ToLower Then
                    For Each subitem In item.SubFolders
                        If subitem.FolderName.ToLower = typepath.ToLower Then
                            returnList.Add(subitem)
                            Return returnList
                        End If
                    Next
                End If
            Next
            Return FileManager.FileTree.SubFolders.First.SubFolders
        Catch ex As Exception
            Logging.LogError(ex, "GetFileTreeDomainAndType")
        End Try
        Return returnList
    End Function
    Public Function GetFileTreeDomainAndTypeAndSubType(ByVal domain As String, ByVal typepath As String, ByVal subtypepath As String) As List(Of ServerFolder) _
      Implements IFileManagerService.GetFileTreeDomainAndTypeAndSubType
        Dim returnList As New List(Of ServerFolder)
        Try
            For Each domainitem In FileManager.FileTree.SubFolders.First.SubFolders
                If domainitem.FolderName.ToLower = domain.ToLower Then
                    For Each typeitem In domainitem.SubFolders
                        If typeitem.FolderName.ToLower = typepath.ToLower Then
                            For Each subitem In typeitem.SubFolders
                                If subitem.FolderName.ToLower = subtypepath.ToLower Then
                                    returnList.Add(subitem)
                                    Return returnList
                                End If
                            Next
                        End If
                    Next
                End If
            Next
            Return FileManager.FileTree.SubFolders.First.SubFolders
        Catch ex As Exception
            Logging.LogError(ex, "GetFileTreeDomainAndTypeAndSubType")
        End Try
        Return returnList
    End Function
    Public Function Reset() As Boolean _
      Implements IFileManagerService.Reset
        FileManager.FileTree.LoadSubfolders()
        Return True
    End Function
#End Region
End Class

Public Class BindEvents
    ''' <summary>
    ''' BindEventsByName binds events .NET Reflection used for dynamic event binding.
    ''' Avoid the numerous Add/RemoveHandler calls
    ''' </summary>
    ''' <remarks>
    ''' You can avoid the numerous Add/RemoveHandler calls by employing a simple convention for 
    ''' naming your event handlers (this is recommended anyway), handlerPrefix[EventName]handlerSufix
    ''' The code doesn't check that the event handler signatures match the event delegates.
    ''' (it would be much more complex in that case)
    ''' When the signatures don't match, the call to CreateDelegate will throw System.ArgumentException at runtime. 
    ''' This is the price you pay for the convenience. 
    ''' </remarks>
    Public Shared Sub BindEventsByName(ByVal sender As Object, ByVal receiver As Object, _
                    ByVal bind As Boolean, ByVal handlerPrefix As String, ByVal handlerSufix As String)

        ' Get the sender's (Subject) public events.
        Dim SenderEvents() As EventInfo = sender.GetType().GetEvents()

        ' Get the receiver's type and lookup its public methods matching the naming convention:
        ' handlerPrefix<EventName>handlerSufix
        Dim ReceiverType As Type = receiver.GetType()
        Dim E As EventInfo
        Dim Method As MethodInfo
        For Each E In SenderEvents
            Method = ReceiverType.GetMethod(handlerPrefix & E.Name & handlerSufix, _
                                            BindingFlags.IgnoreCase Or BindingFlags.Instance Or BindingFlags.Public)

            If Not Method Is Nothing Then
                Dim D As System.Delegate = System.Delegate.CreateDelegate(E.EventHandlerType, receiver, Method.Name)
                If bind Then
                    E.AddEventHandler(sender, D)
                Else
                    E.RemoveEventHandler(sender, D)
                End If
            End If
        Next
    End Sub
    Public Shared Function GetObject(ByVal className As String) As Type
        className = className.Replace("-", "_")
        For Each loadedAssembly In AppDomain.CurrentDomain.GetAssemblies()
            Dim fullname = loadedAssembly.FullName
            Dim classType = loadedAssembly.GetType(className, False, True)
            If Not classType Is Nothing Then
                Return classType
            End If
        Next
        Return Nothing
    End Function
    Public Overloads Shared Function CreateInstanceFromClassName(ByVal ClassName As String) As Object
        Dim ThisClass As Type = GetObject(ClassName)
        If ThisClass Is Nothing Then
            Return Nothing
        Else
            Return Activator.CreateInstance(ThisClass)
        End If
    End Function
    Public Overloads Shared Function CreateInstanceFromClassName(ByVal ClassName As String, ByVal thisObject() As Object) As Object
        Dim ThisClass As Type = GetObject(ClassName)
        If ThisClass Is Nothing Then
            Return Nothing
        Else
            Return Activator.CreateInstance(ThisClass, thisObject)
        End If
    End Function
End Class
